/* Opla Simon Says Created by Julián Caro Linares CC-BY-SA */ // Libraries #include // Definitions #define DEBUG true// Uncomment to see the Serial port debug messages #define SIMON_BLUE 0 #define SIMON_RED 1 #define SIMON_GREEN 3 #define SIMON_YELLOW 4 #define TOUCH_BLUE TOUCH0 #define TOUCH_RED TOUCH1 #define TOUCH_GREEN TOUCH3 #define TOUCH_YELLOW TOUCH4 #define BLUE_TONE 330 // MI #define RED_TONE 262 // DO #define GREEN_TONE 440 // LA #define YELLOW_TONE 294 // SI #define GAMEOVER_TONE 100 // Global variables int difficulty = 1;// Between 1-3 where 1 is the easiest and 3 the hardest int sequence[30]; // 0-BLUE,1-RED,2-GREEN,3-YELLOW //int sequence[10] = {0,1,2,3,0,1,2,3,0,1}; // 0-BLUE,1-RED,2-GREEN,3-YELLOW --TEST SEQUENCE int turn = 0; int delay_time = 500; // Milliseconds bool wait_press = false; bool wrong_button = false; bool difficulty_press =false; // Objects initialization MKRIoTCarrier carrier; uint32_t gameover_color = carrier.leds.Color(0, 255, 0); // Functions declaration void color_animation(char color); // Where b-blue, r-red, g-green, y-yellow void gameover(); void difficulty_selector(); void new_sequence(); void setup() { // Opla setup CARRIER_CASE = true; carrier.begin(); #ifdef DEBUG // Initialize serial and wait for port to open: Serial.begin(9600); // This delay gives the chance to wait for a Serial Monitor without blocking if none is found delay(1500); #endif // Random seed while (!carrier.Light.colorAvailable()) { delay(5); } int none; int light; carrier.Light.readColor(none, none, none, light); randomSeed(light); // TODO create a good seed // Difficulty selector difficulty_selector(); // Sequence generator new_sequence(); // LEDS Initialization carrier.leds.setBrightness(10); carrier.leds.setPixelColor(SIMON_BLUE, 0, 0, 255); // BLUE button GRB notation carrier.leds.setPixelColor(SIMON_RED, 0, 255, 0); // RED button GRB notation carrier.leds.setPixelColor(SIMON_GREEN, 255, 0, 0); // GREEN button GRB notation carrier.leds.setPixelColor(SIMON_YELLOW, 255, 255, 0); // YELLOW button GRB notation carrier.leds.show(); // Delay before starting the game delay(3000); } void loop() { // Begin of the game carrier.leds.clear(); carrier.leds.show(); carrier.display.fillScreen(ST77XX_BLACK); carrier.display.setCursor(35, 100); carrier.display.print("BEGIN"); wrong_button = false; delay(5000); // Turn loop for (int turn = 1; turn <= difficulty * 10; turn ++) { if (wrong_button == true){ #ifdef DEBUG Serial.println("EXIT TURN LOOP"); #endif break; } #ifdef DEBUG Serial.print("\nTurn: "); Serial.println(turn); #endif // Prepare turn if (turn < 10) { carrier.display.setCursor(95, 85); } else { carrier.display.setCursor(65, 85); } carrier.display.fillScreen(ST77XX_BLACK); carrier.display.setTextSize(10); carrier.display.print(turn); // Machine turn for (int j = 0; j < turn; j++) { #ifdef DEBUG Serial.print("Mach index: "); Serial.println(j); Serial.print("Value: "); Serial.println(sequence[j]); #endif carrier.leds.clear(); carrier.leds.show(); switch (sequence[j]) { case 0: // BLUE color_animation('b'); break; case 1: // RED color_animation('r'); break; case 2: // GREEN color_animation('g'); break; case 3: // YELLOW color_animation('y'); break; default: #ifdef DEBUG Serial.println("ERROR: Wrong sequence value"); Serial.println(sequence[j]); #endif break; } } // Player turn for (int k = 0; k < turn; k++) { if (wrong_button == true){ #ifdef DEBUG Serial.println("EXIT PLAYER LOOP"); #endif break; } #ifdef DEBUG Serial.println("PLAYER TURN INDEX"); Serial.println(k); Serial.println("SEQUENCE VALUE: "); Serial.println(sequence[k]); #endif wait_press = false; switch (sequence[k]) { case 0: // BLUE #ifdef DEBUG Serial.println("BLUE CASE"); Serial.print("PLAYER: "); Serial.println(sequence[k]); #endif while (wait_press == false) { carrier.Buttons.update(); if (carrier.Buttons.onTouchDown(TOUCH_BLUE)){ #ifdef DEBUG Serial.println("SUCCESS BLUE"); #endif delay(200); color_animation('b'); wait_press = true; continue; } else if (carrier.Buttons.onTouchDown(TOUCH_RED) || carrier.Buttons.onTouchDown(TOUCH_GREEN) || carrier.Buttons.onTouchDown(TOUCH_YELLOW)){ #ifdef DEBUG Serial.println("BLUE-WRONG BUTTON"); #endif delay(200); wait_press = true; wrong_button = true; gameover(); break; } } break; case 1: // RED #ifdef DEBUG Serial.println("RED CASE"); #endif while (wait_press == false) { carrier.Buttons.update(); if (carrier.Buttons.onTouchDown(TOUCH_RED)){ #ifdef DEBUG Serial.println("SUCCESS RED"); #endif delay(200); color_animation('r'); wait_press = true; continue; } else if (carrier.Buttons.onTouchDown(TOUCH_BLUE) || carrier.Buttons.onTouchDown(TOUCH_GREEN) || carrier.Buttons.onTouchDown(TOUCH_YELLOW)){ #ifdef DEBUG Serial.println("RED-WRONG BUTTON"); #endif delay(200); wait_press = true; wrong_button = true; gameover(); break; } } break; case 2: // GREEN #ifdef DEBUG Serial.println("GREEN CASE"); #endif while (wait_press == false) { carrier.Buttons.update(); if (carrier.Buttons.onTouchDown(TOUCH_GREEN)){ #ifdef DEBUG Serial.println("SUCCESS GREEN"); #endif delay(200); color_animation('g'); wait_press = true; continue; } else if (carrier.Buttons.onTouchDown(TOUCH_RED) || carrier.Buttons.onTouchDown(TOUCH_BLUE) || carrier.Buttons.onTouchDown(TOUCH_YELLOW)){ #ifdef DEBUG Serial.println("GREEN-WRONG BUTTON"); #endif delay(200); wait_press = true; wrong_button = true; gameover(); break; } } break; case 3: // YELLOW #ifdef DEBUG Serial.println("YELLOW CASE"); #endif while (wait_press == false) { carrier.Buttons.update(); if (carrier.Buttons.onTouchDown(TOUCH_YELLOW)){ #ifdef DEBUG Serial.println("SUCCESS YELLOW"); #endif delay(200); color_animation('y'); wait_press = true; continue; } else if (carrier.Buttons.onTouchDown(TOUCH_RED) || carrier.Buttons.onTouchDown(TOUCH_GREEN) || carrier.Buttons.onTouchDown(TOUCH_BLUE)){ #ifdef DEBUG Serial.println("YELLOW-WRONG BUTTON"); #endif delay(200); wait_press = true; wrong_button = true; gameover(); break; } } break; } } } // End catch carrier.leds.clear(); carrier.leds.setPixelColor(2, 255, 0, 0); carrier.leds.show(); carrier.display.fillScreen(ST77XX_BLACK); carrier.display.setTextSize(6); carrier.display.setCursor(70, 100); carrier.display.print("END"); while (true) { carrier.Buttons.update(); if (carrier.Buttons.onTouchUp(TOUCH2)) { carrier.Buzzer.sound(750); delay(250); carrier.Buzzer.noSound(); carrier.display.fillScreen(ST77XX_BLACK); carrier.display.setTextSize(6); carrier.display.setCursor(70, 100); carrier.display.print("NEW"); delay(3000); break; } delay(500); } // New game sequence difficulty_selector(); new_sequence(); delay(2000); // Time to see the difficulty selected } void difficulty_selector(){ carrier.leds.setBrightness(10); carrier.leds.setPixelColor(1, 255, 0, 0); // EASY carrier.leds.setPixelColor(2, 0, 0, 255); // NORMAL carrier.leds.setPixelColor(3, 0, 255, 0); // HARD carrier.leds.show(); carrier.display.setRotation(0); carrier.display.setTextSize(3); carrier.display.fillScreen(ST77XX_BLACK); carrier.display.setCursor(35, 110); carrier.display.print("DIFFICULTY"); difficulty_press = false; while (difficulty_press == false) { carrier.Buttons.update(); if (carrier.Buttons.onTouchDown(TOUCH1)){ difficulty = 1; difficulty_press = true; } else if (carrier.Buttons.onTouchDown(TOUCH2)){ difficulty = 2; difficulty_press = true; } else if (carrier.Buttons.onTouchDown(TOUCH3)){ difficulty = 3; difficulty_press = true; } delay(100); } } void new_sequence(){ carrier.display.fillScreen(ST77XX_BLACK); carrier.display.setRotation(0); carrier.display.setTextSize(6); switch (difficulty) { default: //Like case 1 case 1: carrier.display.setCursor(55, 100); carrier.display.print("EASY"); for (int i = 0; i < 10; i++) { sequence[i] = random(0, 4); #ifdef DEBUG Serial.print("Sequence:"); Serial.println(i); Serial.println(sequence[i]); #endif } break; case 2: carrier.display.setCursor(17, 100); carrier.display.print("NORMAL"); for (int i = 0; i < 20; i++) { sequence[i] = random(0, 4); #ifdef DEBUG Serial.print("Sequence:"); Serial.println(i); Serial.println(sequence[i]); #endif } break; case 3: carrier.display.setCursor(50, 100); carrier.display.print("HARD"); for (int i = 0; i < 30; i++) { sequence[i] = random(0, 4); #ifdef DEBUG Serial.print("Sequence:"); Serial.println(i); Serial.println(sequence[i]); #endif } break; } } void color_animation(char color){ switch (color){ case 'b': // ON carrier.leds.setPixelColor(SIMON_BLUE, 0, 0, 255); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_BLUE); carrier.Buzzer.sound(BLUE_TONE); delay(delay_time); // OFF carrier.Buzzer.noSound(); carrier.leds.clear(); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_BLACK); delay(delay_time); break; case 'r': // ON carrier.leds.setPixelColor(SIMON_RED, 0, 255, 0); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_RED); carrier.Buzzer.sound(RED_TONE); delay(delay_time); // OFF carrier.Buzzer.noSound(); carrier.leds.clear(); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_BLACK); delay(delay_time); break; case 'g': // ON carrier.leds.setPixelColor(SIMON_GREEN, 255, 0, 0); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_GREEN); carrier.Buzzer.sound(GREEN_TONE); delay(delay_time); // OFF carrier.Buzzer.noSound(); carrier.leds.clear(); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_BLACK); delay(delay_time); break; case 'y': // ON carrier.leds.setPixelColor(SIMON_YELLOW, 255, 255, 0); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_YELLOW); carrier.Buzzer.sound(YELLOW_TONE); delay(delay_time); // OFF carrier.Buzzer.noSound(); carrier.leds.clear(); carrier.leds.show(); //carrier.display.fillScreen(ST77XX_BLACK); delay(delay_time); break; } } void gameover(){ #ifdef DEBUG Serial.println("GAMEOVER"); #endif // ON carrier.leds.fill(gameover_color, 0, 5); carrier.leds.show(); carrier.Buzzer.sound(GAMEOVER_TONE); carrier.display.fillScreen(ST77XX_RED); carrier.display.setTextSize(4); carrier.display.setCursor(25, 105); carrier.display.print("GAMEOVER"); delay(2000); // OFF carrier.Buzzer.noSound(); //carrier.display.fillScreen(ST77XX_BLACK); delay(5000); }